﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using UploadClient.Interfaces;
using UploadClient.Interfaces.Upload;

namespace DropBoxUploadPlugin
{
    class DropBoxUpload : IUploadProvider
    {
        Configuration config;
        int finishedFiles;

        bool init = false;
        Upload upload;
        List<IUploadItem> uploadQue;
        UserState userState;

        #region IUploadProvider Members

        public event UploadCompleteEventHandler UploadComplete;
        public event UploadProgressEventHandler UploadProgress;

        public void Init(IUploadHost host)
        {
            upload = new Upload();
            upload.WorkerReportsProgress = true;
            upload.WorkerSupportsCancellation = true;
            upload.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Upload_RunWorkerCompleted);
            upload.ProgressChanged += new ProgressChangedEventHandler(Upload_ProgressChanged);
            upload.Host = host;

            config = new Configuration();
            uploadQue = new List<IUploadItem>();

            init = true;

            //temp -----------------------------------------------
            //IServerSettings settings = new IServerSettings();
            //settings.Dir = "/testfolder";
            //settings.Username = "mail";
            //settings.Password = "pw";

            //UploadItem item = new UploadItem();
            //item.Filepath = @"C:\\DummyData";
            //item.ServerSettings = settings;

            //UploadFiles(item);
            //temp -----------------------------------------------
        }

        public void Init(IUploadHost host, IUploadConfig settings)
        {
            Init(host);
            config = new Configuration(settings.Settings);
        }

        public IEnumerable<IUploadConfig> GetConfiguration()
        {
            return init ? new IUploadConfig[] { config } : new IUploadConfig[] { };
        }

        public void UploadFiles(params IUploadItem[] items)
        {
            if (init)
            {
                if (uploadQue.Count() == 0) finishedFiles = 0;
                uploadQue.AddRange(items);
                StartUpload();
            }
        }

        public void CancelUpload()
        {
            if (init)
            {
                upload.CancelAsync();
                uploadQue.Clear();
            }
        }

        public bool IsBusy
        {
            get { return init ? upload.IsBusy || uploadQue.Count > 0 : false; }
            private set { IsBusy = value; }
        }

        public int GetRemainingQueCount()
        {
            if (init) return uploadQue.Count() + userState.GetRemainingQueCount - userState.GetFinishedFilesCount;
            else return -1;
        }

        public int GetFinishedFilesCount()
        {
            if (init) return finishedFiles + userState.GetFinishedFilesCount;
            else return -1;
        }

        public void Dispose()
        {
            this.Dispose();
        }

        #endregion

        private void StartUpload()
        {
            if (!upload.IsBusy && uploadQue.Count > 0)
            {
                UploadItem tempItem = uploadQue.First() as UploadItem;

                var x = from item in uploadQue
                        where item.ServerSettings.Username.Equals(tempItem.ServerSettings.Username)
                              && item.ServerSettings.Password.Equals(tempItem.ServerSettings.Password)
                        select item;

                upload.RunWorkerAsync(x.ToArray());

                // del selected
                var res = uploadQue.Where(item => !(item.ServerSettings.Username.Equals(tempItem.ServerSettings.Username)
                                                    && item.ServerSettings.Password.Equals(tempItem.ServerSettings.Password)));
                uploadQue.Clear();
                uploadQue = res.ToList();
            }
        }

        private void Upload_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (UploadComplete != null)
            {
                if (uploadQue.Count > 0 && e.Error == null && !e.Cancelled)
                {
                    finishedFiles += userState.GetFinishedFilesCount;
                    StartUpload();
                }
                else
                {
                    // ToDo: multilang & pares errors
                    UploadEventArgs args = new UploadEventArgs(config.Guid, e.Error, e.Cancelled, "Exception occured, upload has stoped, que has been cleared!");
                    UploadComplete(args);
                }
            }
            uploadQue.Clear();
        }

        private void Upload_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (UploadProgress != null)
            {
                userState = (UserState)e.UserState;
                UploadProgressEventArgs args = new UploadProgressEventArgs(config.Guid, e.ProgressPercentage, userState.Message);
                UploadProgress(args);
            }
        }
    }
}
